package com.qs.commontools.utils.regular;

import com.qs.commontools.constants.RegularConstant;
import com.qs.commontools.utils.base.StringUtils;

import java.util.regex.Pattern;

/**
 * 正则工具类
 * @author qiusuo
 * @since 2021-09-29
 */
public class RegularUtils {

    /**
     * 校验入参是否是年份，范围0001-9999。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkYear(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.IS_YEAR.matcher(str).matches();
    }

    /**
     * 校验手机号码。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkPhone(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.CHINA_PHONE.matcher(str).matches();
    }

    /**
     * 大陆座机正则。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkPhoneLandline(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.CHINA_LANDLINE.matcher(str).matches();
    }

    /**
     * 香港手机号码8位数，5|6|8|9开头+7位任意数。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkPhoneHK(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.HK_PATTERN.matcher(str).matches();
    }

    /**
     * 判断是否是正整数的方法。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumPositiveInteger(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.POSITIVE_INTEGER.matcher(str).matches();
    }


    /**
     * 判断入参是否是非负整数。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumPositiveZeroInt(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.POSITIVE_ZERO_INTEGER.matcher(str).matches();
    }

    /**
     * 判断入参是否是非正整数。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumNegativeZeroInt(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NEGATIVE_ZERO_INTEGER.matcher(str).matches();
    }

    /**
     * 判断是否是数字。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNum(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NUM.matcher(str).matches();
    }

    /**
     * 判断是否是整数格式字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumInteger(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.INTEGER.matcher(str).matches();
    }

    /**
     * 判断是否是n位的数字字符串。
     *
     * @param str 需要被校验的字符串
     * @param len n位数字长度
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumInteger(String str,Integer len) {
        Pattern pattern = Pattern.compile("^\\d{" + len + "}$");
        return StringUtils.isBlank(str) ? false : pattern.matcher(str).matches();
    }

    /**
     * 判断是否至少n位的数字字符串。
     *
     * @param str 需要被校验的字符串
     * @param len 至少n位数字长度
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumIntAtLeast(String str,Integer len) {
        len = null == len ? 0 :len;
        Pattern pattern = Pattern.compile("^\\d{" + len + ",}$");
        return StringUtils.isBlank(str) ? false : pattern.matcher(str).matches();
    }

    /**
     * 判断是否m-n位的数字字符串。
     *
     * @param str 需要被校验的字符串
     * @param m 至少多少位
     * @param n 至多多少位
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumIntRange(String str, Integer m, Integer n) {
        m = null == m ? 0 :m;
        n = null == n ? 0 :n;
        Pattern pattern = Pattern.compile("^\\d{" + m + "," + n + "}$");
        return StringUtils.isBlank(str) ? false : pattern.matcher(str).matches();
    }

    /**
     * 判断是否是浮点数格式字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumFloat(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NUM_FLOAT.matcher(str).matches();
    }

    /**
     * 判断是否是非负数浮点数字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumFloatPositiveZero(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NUM_FLOAT_POSITIVE_ZERO.matcher(str).matches();
    }

    /**
     * 判断是否是正浮点数字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumFloatPositive(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NUM_FLOAT_POSITIVE.matcher(str).matches();
    }

    /**
     * 判断是否是非正浮点数字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumFloatNegativeZero(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NUM_FLOAT_NEGATIVE_ZERO.matcher(str).matches();
    }

    /**
     * 判断是否是负浮点数字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumFloatNegative(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.NUM_FLOAT_NEGATIVE.matcher(str).matches();
    }

    /**
     * 判断是否带m-n位小数的正数或负数字符串。
     *
     * @param str 需要被校验的字符串
     * @param m 至少多少位小数
     * @param n 至多多少位小数
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNumFloatRange(String str, Integer m, Integer n) {
        m = null == m ? 0 :m;
        n = null == n ? 2 :n;
        Pattern pattern = Pattern.compile("^(\\-)?\\d+(\\.\\d{" + m + "," + n + "})?$");
        return StringUtils.isBlank(str) ? false : pattern.matcher(str).matches();
    }

    /**
     * 判断是否是n位小数的正实数字符串。
     * 默认1位小数
     *
     * @param str 需要被校验的字符串
     * @param m 多少位小数
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkNum(String str, Integer m) {
        m = null == m ? 1 :m;
        Pattern pattern = Pattern.compile("^[0-9]+(.[0-9]{" + m + "})?$");
        return StringUtils.isBlank(str) ? false : pattern.matcher(str).matches();
    }

    /**
     * 判断是否是邮箱格式字符串。
     * <br>
     * <br>示例：https://gitee.com/big-suo/common-tools/blob/develop/src/test/java/com/qs/commontools/regular/RegularTest.java
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkEmail(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.EMAIL.matcher(str).matches();
    }

    /**
     * 判断是否是邮政编码格式字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkPostCode(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.POSTAL_CODE.matcher(str).matches();
    }

    /**
     * 判断是否符合账号格式字符串。
     * 以英文字符开头，英文和数字组合，4-15位。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkAccount1(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ACCOUNT1.matcher(str).matches();
    }

    /**
     * 判断是否符合账号格式字符串。
     * 英文数字括号$¥和-_.
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkAccount2(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ACCOUNT2.matcher(str).matches();
    }


    /**
     * 判断是否符合名称字符串。
     * 中英文。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkName(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ACCOUNT_NAME.matcher(str).matches();
    }

    /**
     * 判断是否符合普通身份证号码格式字符串，15和18位皆可。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkIdCard(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ID_CARD.matcher(str).matches();
    }


    /**
     * 判断是否符合普通身份证号码格式字符串，18位。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkIdCard18(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ID_CARD18.matcher(str).matches();
    }

    /**
     * 判断是否符合普通身份证号码格式字符串，15位。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkIdCard15(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ID_CARD15.matcher(str).matches();
    }

    /**
     * 判断身份证号后6位格式字符串是否正确。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkIdCardSuffix6(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ID_CARD_SUFFIX6.matcher(str).matches();
    }

    /**
     * 判断是否是汉字组成的字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkZhCn(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ZH_CN.matcher(str).matches();
    }

    /**
     * 判断是否是26个英文字母组成的字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkEn(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.EN_STR.matcher(str).matches();
    }

    /**
     * 判断是否是26个大写英文字母组成的字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkEnUp(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.EN_UP.matcher(str).matches();
    }

    /**
     * 判断是否是26个小写英文字母组成的字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkEnLow(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.EN_LOW.matcher(str).matches();
    }

    /**
     * 判断是否是由数字和26个英文字母组成的字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkEnNum(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.EN_NUM.matcher(str).matches();
    }

    /**
     * 判断是否是由中文、英文、数字包括下划线组成的字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkZhEnNumUnderline(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.ZH_EN_NUM_LAIN.matcher(str).matches();
    }

    /**
     * 判断是否是IP字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkIP(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.IP.matcher(str).matches();
    }

    /**
     * 判断是否是标签对字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkTag(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.TAG.matcher(str).matches();
    }

    /**
     * 判断是否是Http类型URL字符串。
     *
     * @param str 需要被校验的字符串
     * @return 校验正确：<code>true</code>,校验失败：<code>fasle</code>
     */
    public static boolean checkHttpURL(String str) {
        return StringUtils.isBlank(str) ? false : RegularConstant.HTTP_URL.matcher(str).matches();
    }
}
